/*-------------------------------------------------------------------------
 - Copyright (c) 2024-2025 [XD-AMCC TEAM]
 - [XD-AMCC] is licensed under Mulan PSL v2.
 - You can use this software according to the terms and conditions of the Mulan PSL v2.
 - You may obtain a copy of Mulan PSL v2 at:
 -          http://license.coscl.org.cn/MulanPSL2
 - THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES
 - OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
 - TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 - See the Mulan PSL v2 for more details.
 ------------------------------------------------------------------------*/


/**
 * @file
 * @brief Interface of abstract class reference-counter.
 *
 * @author  WXQ#XDU
 * @date    2024.11
 */

#pragma once

#ifndef AMCC_REFCOUNT_H
#define AMCC_REFCOUNT_H

#include "amcc_config.h"

AMCC_DECL_BEGIN


/**
 * @brief Reference counter to user-defined shared data.
 *
 * This class is the common abstract base class for
 * - all attributes classes,
 * - all types, and ...
 *
 * The original intention of this class is to reduce
 * the overhead required for attributes/types copying or passing,
 * AND, avoid double-free a shared pointer.
 *
 * An example of this class is "t_attr_directDeclarator"
 * which is defined in symtable/inside/stb_inner.h.
 */
typedef struct reference_count {
    int  refCount; //!< counter of references to this object

    /// Callback function which destroys the concrete shared user-data.
    /// In user's callback function, DON'T call free(pThis)!!!
    void (* free)(struct reference_count * pThis);
} t_reference, * t_reference_ptr ;

/// Type of callback function which destroys the
/// concrete shared user-data
typedef void (* t_reference_free)(t_reference_ptr referencePtr);

/**
 * @brief Initialize common data for the given reference object.
 * @param referencePtr  pointer to a reference object
 * @param pFuncFree   pointer to a callback function which destroys
 *                    a use-defined, concrete reference object
 */
extern void ref_init_(t_reference_ptr referencePtr,
                      t_reference_free pFuncFree);

/**
 * @brief Make a copy of the given reference object.
 *
 * This operation just increases the reference counter.
 *
 * @param referencePtr  pointer to a reference object
 * @return Return the modified reference object.
 */
extern t_reference_ptr ref_copy_(t_reference_ptr referencePtr);

/**
 * @brief Destroy the given reference object.
 *
 * This operation firstly decreases the reference counter,
 * and ONLY if this counter is down to zero, the free-function
 * specified by ref_init_() will be invoked.
 *
 * @param referencePtr  pointer to a reference object
 */
extern void ref_free_(t_reference_ptr referencePtr);



AMCC_DECL_END


#endif //AMCC_REFCOUNT_H
